﻿using System;

using Fuse8.DomainFramework.Common.Locator;
using Fuse8.DomainFramework.BusinessService;
using Fuse8.DomainFramework.Domain;
using Fuse8.DomainFramework.DataAccess;

namespace Fuse8.DomainFramework.Configuration.Fluent
{    
    /// <summary>
    /// 
    /// </summary>
    public interface IFrameworkConfigurationBuilder
    {
        /// <summary>
        /// 
        /// </summary>
        /// <returns></returns>
        IFrameworkConfigurationDependencyContainerBuilder UseDependencyContainer();
    }

    /// <summary>
    /// 
    /// </summary>
    public interface IFrameworkConfigurationDependencyContainerBuilder : IFrameworkConfigurationBuilder
    {
        /// <summary>
        /// 
        /// </summary>
        /// <param name="newProvider"></param>
        /// <returns></returns>
        IFrameworkConfigurationServicesBuilder SetLocatorProvider(ServiceLocatorProviderEx newProvider);

        /// <summary>
        /// 
        /// </summary>
        /// <param name="newProvider"></param>
        /// <returns></returns>
        IFrameworkConfigurationServicesBuilder SetLocatorProvider(ServiceLocatorProviderWithLazy newProvider);
    }

    /// <summary>
    /// 
    /// </summary>
    public interface IFrameworkConfigurationServicesBuilder
    {
        /// <summary>
        /// 
        /// </summary>
        /// <returns></returns>
        IFrameworkConfigurationBusinessServicesBuilder BusinessServicesConfiguration();

        /// <summary>
        /// 
        /// </summary>
        /// <returns></returns>
        IFrameworkConfigurationDataAccessBuilder DataAccessConfiguration();

        /// <summary>
        /// 
        /// </summary>
        void Build();
    }

    /// <summary>
    /// 
    /// </summary>
    public interface IFrameworkConfigurationBusinessServicesBuilder : IFrameworkConfigurationServicesBuilder
    {
        /// <summary>
        /// 
        /// </summary>
        /// <typeparam name="TEntity"></typeparam>
        /// <typeparam name="TKey"></typeparam>
        /// <param name="service"></param>
        /// <returns></returns>
        IFrameworkConfigurationBusinessServicesBuilder RegisterBusinessService<TEntity, TKey>(IEntityBusinessService<TEntity, TKey> service)
            where TEntity : class, IEntityObject<TKey>
            where TKey : IComparable<TKey>, IEquatable<TKey>;
    }

    /// <summary>
    /// 
    /// </summary>
    public interface IFrameworkConfigurationDataAccessBuilder : IFrameworkConfigurationServicesBuilder
    {
        /// <summary>
        /// 
        /// </summary>
        /// <param name="repositoryType"></param>
        /// <returns></returns>
        IFrameworkConfigurationDataAccessBuilder SetDefaultUnitOfWorkFactory(IFrameworkDataRepositoryType repositoryType);

        /// <summary>
        /// 
        /// </summary>
        /// <returns></returns>
        IFrameworkConfigurationDataAccessBuilder SetDefaultDataRepository();
    }

    /// <summary>
    /// 
    /// </summary>
    public interface IFrameworkConfigurationDataAccessBuilder<TEntity, TKey> : IFrameworkConfigurationDataAccessBuilder
        where TEntity : class, IEntityObject<TKey>, new()
        where TKey : IComparable<TKey>, IEquatable<TKey>
    {
        /// <summary>
        /// 
        /// </summary>
        /// <param name="factory"></param>
        /// <returns></returns>
        IFrameworkConfigurationDataAccessBuilder<TEntity, TKey> RegisterUnitOfWorkFactory(IUnitOfWorkFactory<TEntity> factory);

        /// <summary>
        /// 
        /// </summary>
        /// <param name="dataRepository"></param>
        /// <returns></returns>
        IFrameworkConfigurationDataAccessBuilder<TEntity, TKey> RegisterDataRepository(IEntityDataRepository<TEntity, TKey> dataRepository);
        
        /// <summary>
        /// 
        /// </summary>
        /// <typeparam name="TRepository"></typeparam>
        /// <param name="dataMapper"></param>
        /// <returns></returns>
        IFrameworkConfigurationDataAccessBuilder<TEntity, TKey> RegisterDataMapper<TRepository>(IEntityDataRepositoryMapper<TEntity, TRepository> dataMapper)
            where TRepository : class;
    }
}
